package com.bangdao.juc;

/**
 * @author chen
 * @create 2021-01-02
 */

/**
 * 两个线程操作一个初始值为0的变量，实现一个线程对变量增加1，
 * 一个线程对变量减少1，交替10轮。
 * 换成4个线程会导致错误，**虚假唤醒**
 * 原因：在java多线程判断时，不能用if，程序出事出在了判断上面。
 * **注意，消费者被唤醒后是从wait()方法（被阻塞的地方）后面执行，而不是重新从同步块开头。
 * if只判断一次，while是只要唤醒就要拉回来再判断一次。
 */
public class WaitNotifyDemo {
    public static void main(String[] args) {
        ShareDataOne dataOne = new ShareDataOne();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    dataOne.incr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "a").start();
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    dataOne.decr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "b").start();
    }
}

/**
 * 资源类
 */
class ShareDataOne {
    private Integer num = 0;

    public synchronized void incr() throws InterruptedException {
        //判断
        while (num != 0) {
            this.wait();
        }
        //干活
        num++;
        System.out.println(Thread.currentThread().getName() + ":" + num);
        //通知
        this.notifyAll();
    }

    public synchronized void decr() throws InterruptedException {
        //判断
        while (num != 1) {
            this.wait();
        }
        //干活
        num--;
        System.out.println(Thread.currentThread().getName() + ":" + num);
        //通知
        this.notifyAll();
    }
}
